package sharemem

import (
	"server_cluster/common/config"
	"server_cluster/common/gdconf"
	"server_cluster/common/logger"
	"server_cluster/common/protoc/pb"
)

type ModifySkillEffect struct {
	SkillId      int32
	EffectIdList []int32
}

type ModifySkillEffectParam struct {
	EffectId           int32
	Param1             [][]int32
	Param2             [][]int32
	Param3             int32
	Param4             int32
	Param5             int32
	Param6             []int32
	ClientEffectIdList []int32
}

// PacketPbFightData 打包战斗数据
func PacketPbFightData(user *User, battleGroupId int32, activeFight bool, trailGroupId int32) *pb.ServerUserFightData {
	pbFightData := &pb.ServerUserFightData{
		BattleGroupId: battleGroupId,
		FightRole:     make([]*pb.BaseInfo, 0),
		AssistRole:    make([]*pb.BaseInfo, 0),
		Status:        activeFight,
		Timestamp:     MyShm.TimeNow,
		CaptainSkill:  user.GetCaptainSkill(),
	}
	activeTeamId := user.GetActiveTeamId()
	team := user.GetTeam(activeTeamId)
	if team == nil {
		logger.Error("no active team, activeTeamId: %v, uid: %v", activeTeamId, user.GetUid())
		return nil
	}

	var trailRoleList = gdconf.GetTrailRoleList(trailGroupId)
	for roleIndex, roleId := range team.GetFightRoleList() {
		var ifReplace = false
		if trailRoleList != nil {
			for _, v := range trailRoleList {
				var trailConfig = gdconf.GetTrailRoleConfig4TrailId(v)
				if trailConfig != nil {
					if roleIndex == int(trailConfig.Position) {
						ifReplace = true
						pbFightData.FightRole =
							append(pbFightData.FightRole, PacketRoleFightBaseInfo(user, roleIndex, trailConfig.RoleId, false, trailConfig.Id))
					}
				}
			}
		}
		if !ifReplace && roleId != 0 {
			pbFightData.FightRole =
				append(pbFightData.FightRole, PacketRoleFightBaseInfo(user, roleIndex, roleId, false, 0))
		}
	}
	for roleIndex, roleId := range team.GetAssistRoleList() {
		var ifReplace = false
		if trailRoleList != nil {
			for _, v := range trailRoleList {
				var trailConfig = gdconf.GetTrailRoleConfig4TrailId(v)
				if trailConfig != nil {
					if roleIndex == int(trailConfig.Position-4) {
						ifReplace = true
						pbFightData.AssistRole =
							append(pbFightData.AssistRole, PacketRoleFightBaseInfo(user, roleIndex, trailConfig.RoleId, true, trailConfig.Id))
					}
				}
			}
		}
		if !ifReplace && roleId != 0 {
			pbFightData.AssistRole =
				append(pbFightData.AssistRole, PacketRoleFightBaseInfo(user, roleIndex, roleId, true, 0))
		}
	}
	return pbFightData
}
func PacketRoleFightBaseInfo(user *User, roleIndex int, roleId int32, isAssistRole bool, trailId int32) *pb.BaseInfo {
	if trailId != 0 {
		var trailRoleConfig = gdconf.GetTrailRoleConfig4TrailId(trailId)
		var role = new(Role)
		role.Id.NewVal = trailRoleConfig.RoleId
		role.Level = int16(trailRoleConfig.Level)
		role.Star = int8(trailRoleConfig.Star)
		for _, v := range trailRoleConfig.TalentList {
			for i := 0; i < len(v)/2; i++ {
				role.AddTalent(v[2*i])
				var pTalent = role.GetTalent(v[2*i])
				if pTalent != nil {
					pTalent.Level = int8(v[2*i+1])
				}
			}
		}
		return packetRoleFightBaseInfo(user, roleIndex, role, isAssistRole, trailId)
	} else {
		role := user.GetRoleById(roleId)
		if role == nil {
			logger.Error("get user role is nil, roleId: %v, uid: %v", roleId, user.GetUid())
			return nil
		}
		return packetRoleFightBaseInfo(user, roleIndex, role, isAssistRole, 0)
	}
}

func packetRoleFightBaseInfo(user *User, roleIndex int, role *Role, isAssistRole bool, trailId int32) *pb.BaseInfo {
	// 战斗属性
	var roleId = role.GetId()
	fightPropMap := user.GetUserRoleFightProp4Trail(role, trailId)
	if !isAssistRole {
		fightPropMap[config.FIGHT_PROP_ENERGY_REC] = 0
	}
	fightPropMap[config.FIGHT_PROP_WEAPON_POWER] = int32(role.Level)
	pbProp := make([]*pb.Attr, 0, len(fightPropMap))
	for k, v := range fightPropMap {
		attr := &pb.Attr{Id: k, Val: v}
		pbProp = append(pbProp, attr)
	}
	// 当前生命值
	pbProp = append(pbProp, &pb.Attr{
		Id: config.FIGHT_PROP_CUR_HP,
		// Val: role.CurrHp,
		// TODO
		Val: fightPropMap[config.FIGHT_PROP_HP],
	})
	if trailId != 0 {
		// 试炼角色满怒气
		pbProp = append(pbProp, &pb.Attr{
			Id:  config.FIGHT_PROP_CUR_ENERGY,
			Val: fightPropMap[config.FIGHT_PROP_ENERGY],
		})
	} else {
		// 当前怒气值
		pbProp = append(pbProp, &pb.Attr{
			Id:  config.FIGHT_PROP_CUR_ENERGY,
			Val: role.CurrEnergy,
		})
	}
	// 平均装等
	//weaponPower := int32(1)
	//equipList := user.GetUserRoleEquipListByPtr(role)
	//if len(equipList) > 0 {
	//	for _, equip := range equipList {
	//		equipConfig := gdconf.GetEquipConfig(equip.GetId())
	//		if equipConfig == nil {
	//			continue
	//		}
	//		weaponPower += equipConfig.WeaponPower
	//	}
	//	weaponPower = int32(float32(weaponPower) / float32(len(equipList)))
	//}

	// 技能
	roleConfig := gdconf.GetRoleConfig(roleId)
	if roleConfig == nil {
		return nil
	}
	roleStarConfig := gdconf.GetRoleStarConfigByGroupAndStar(roleConfig.StarGroup, int32(role.Star))
	if roleStarConfig == nil {
		return nil
	}
	// 普攻序列
	normalAttackQueue := make([]*pb.AttackQueue, 0)
	if !isAssistRole {
		for _, normalAttackSkill := range roleStarConfig.NormalAttackSkillList {
			normalAttackQueue = append(normalAttackQueue, &pb.AttackQueue{
				Card:   normalAttackSkill.SkillCardId,
				CdTime: normalAttackSkill.CdTime,
			})
		}
	}
	// 被动技能
	passiveSkill := make([]int32, 0, len(roleStarConfig.PassiveSkill))
	// 角色被动技能
	for _, skill := range roleStarConfig.PassiveSkill {
		passiveSkill = append(passiveSkill, skill)
	}
	// 装备被动技能 //新增需要累加所有装备的技能强度等级
	equip_skill_level := make(map[int32]int32)

	equipSkillList := user.GetEquipSkillList(user.GetUserRoleEquipListByPtr(role))
	for _, v := range equipSkillList {
		_, ok := equip_skill_level[v.SkillGroup]
		if !ok {
			equip_skill_level[v.SkillGroup] = v.Level
		} else {
			equip_skill_level[v.SkillGroup] += v.Level
		}
	}

	for k, v := range equip_skill_level {
		var equipSkillConfig *gdconf.EquipSkillConfig = nil
		for lv := v; lv > 0; lv-- {
			equipSkillConfig = gdconf.GetConfigEquipSkillByGroupAndLevel(k, lv)
			if equipSkillConfig != nil {
				break
			}
		}
		if equipSkillConfig == nil {
			logger.Error("1can not find max level equip skill config, skillGroup: %v, level: %v, uid: %v", k, v, user.GetUid())
			continue
		}
		logger.Info("equipSkillConfig = %v", equipSkillConfig)
		for _, skillId := range equipSkillConfig.SkillIdList {
			passiveSkill = append(passiveSkill, skillId)
		}
	}

	if trailId == 0 {
		weapon := user.GetUserRoleWeaponByPtr(role)
		if weapon != nil {
			weaponConfig := gdconf.GetWeaponConfig(weapon.ItemId)
			if weaponConfig == nil {
				return nil
			}
			weaponStarConfig := gdconf.GetWeaponStarConfigByGroupAndStar(weaponConfig.StarGroup, int32(weapon.Star))
			if weaponStarConfig == nil {
				return nil
			}
			for _, skillId := range weaponStarConfig.Passive {
				passiveSkill = append(passiveSkill, skillId)
			}
		}
	}
	// 天赋技能效果修改器
	modifySkillEffectMap := make(map[int32]*ModifySkillEffect, 0)
	modifySkillEffectParamMap := make(map[int32]*ModifySkillEffectParam, 0)
	for _, effectModifier := range role.GetTalentEffectModifierList() {
		logger.Debug("do effect modifier: %+v", effectModifier)
		switch effectModifier.ModifierType {
		case
			gdconf.EffectModifierTypeChangeDamagePercentage,
			gdconf.EffectModifierTypeChangeBuffId,
			gdconf.EffectModifierTypeChangeBuffLayer,
			gdconf.EffectModifierTypeChangeTempProp,
			gdconf.EffectModifierTypeChangeParam4,
			gdconf.EffectModifierTypeChangeParam5,
			gdconf.EffectModifierTypeAddDamageByBuffCount,
			gdconf.EffectModifierTypeAddDamageByTargetState:
			modifySkillEffectParam, exist := modifySkillEffectParamMap[effectModifier.EffectId]
			if !exist {
				battleSubSkillEffectConfig := gdconf.GetBattleSubSkillEffectConfig(effectModifier.EffectId)
				if battleSubSkillEffectConfig == nil {
					continue
				}
				modifySkillEffectParam = &ModifySkillEffectParam{
					EffectId:           effectModifier.EffectId,
					Param1:             battleSubSkillEffectConfig.GetParam1(),
					Param2:             battleSubSkillEffectConfig.GetParam2(),
					Param3:             battleSubSkillEffectConfig.Param3,
					Param4:             battleSubSkillEffectConfig.Param4,
					Param5:             battleSubSkillEffectConfig.Param5,
					Param6:             battleSubSkillEffectConfig.GetParam6(),
					ClientEffectIdList: battleSubSkillEffectConfig.GetClientEffectIdList(),
				}
				modifySkillEffectParamMap[effectModifier.EffectId] = modifySkillEffectParam
			}
			switch effectModifier.ModifierType {
			case gdconf.EffectModifierTypeChangeDamagePercentage:
				modifySkillEffectParam.Param1[effectModifier.ParamIndex][2] += effectModifier.Value
			case gdconf.EffectModifierTypeChangeBuffId:
				modifySkillEffectParam.Param1[effectModifier.ParamIndex] = modifySkillEffectParam.Param1[effectModifier.ParamIndex][:2]
				modifySkillEffectParam.Param1[effectModifier.ParamIndex] = append(modifySkillEffectParam.Param1[effectModifier.ParamIndex], effectModifier.Group...)
			case gdconf.EffectModifierTypeChangeBuffLayer:
				modifySkillEffectParam.Param1[effectModifier.ParamIndex][2] = effectModifier.Value
			case gdconf.EffectModifierTypeChangeTempProp:
				add := true
				for _, a := range modifySkillEffectParam.Param2 {
					if a[0] == effectModifier.Key {
						a[1] += effectModifier.Value
						add = false
						break
					}
				}
				if add {
					modifySkillEffectParam.Param2 = append(modifySkillEffectParam.Param2, []int32{effectModifier.Key, effectModifier.Value})
				}
			case gdconf.EffectModifierTypeChangeParam4:
				modifySkillEffectParam.Param4 = effectModifier.Value
			case gdconf.EffectModifierTypeChangeParam5:
				modifySkillEffectParam.Param5 = effectModifier.Value
			case gdconf.EffectModifierTypeAddDamageByBuffCount:
				if len(modifySkillEffectParam.Param6) == 5 {
					modifySkillEffectParam.Param6[4] += effectModifier.Value
				}
			case gdconf.EffectModifierTypeAddDamageByTargetState:
				if len(modifySkillEffectParam.Param6) == 4 {
					modifySkillEffectParam.Param6[3] += effectModifier.Value
				}
			}
		case gdconf.EffectModifierTypeAddSkillEffect:
			modifySkillEffect, exist := modifySkillEffectMap[effectModifier.SkillId]
			if !exist {
				battleSubSkillConfig := gdconf.GetBattleSubSkillConfig(effectModifier.SkillId)
				if battleSubSkillConfig == nil {
					continue
				}
				modifySkillEffect = &ModifySkillEffect{
					SkillId:      effectModifier.SkillId,
					EffectIdList: battleSubSkillConfig.GetEffectIdList(),
				}
				modifySkillEffectMap[effectModifier.SkillId] = modifySkillEffect
			}
			modifySkillEffect.EffectIdList = append(modifySkillEffect.EffectIdList, effectModifier.EffectId)
		}
	}
	pbModifySkillEffectList := make([]*pb.ConfigEffect, 0, len(modifySkillEffectMap))
	for _, modifySkillEffect := range modifySkillEffectMap {
		pbModifySkillEffectList = append(pbModifySkillEffectList, &pb.ConfigEffect{
			Id:          modifySkillEffect.SkillId,
			SkillEffect: modifySkillEffect.EffectIdList,
		})
	}
	pbModifySkillEffectParamList := make([]*pb.ConfigEffectParam, 0, len(modifySkillEffectParamMap))
	for _, modifySkillEffectParam := range modifySkillEffectParamMap {
		pbModifySkillEffectParamList = append(pbModifySkillEffectParamList, &pb.ConfigEffectParam{
			Id:         modifySkillEffectParam.EffectId,
			Param1:     PacketPbIntArrayArray(modifySkillEffectParam.Param1),
			Param2:     PacketPbIntArrayArray(modifySkillEffectParam.Param2),
			Param3:     modifySkillEffectParam.Param3,
			Param4:     modifySkillEffectParam.Param4,
			Param5:     modifySkillEffectParam.Param5,
			Param6:     modifySkillEffectParam.Param6,
			ShowEffect: modifySkillEffectParam.ClientEffectIdList,
		})
	}
	return &pb.BaseInfo{
		Id:             roleId,
		Site:           int32(roleIndex),
		ExCard:         roleStarConfig.ExSkillCardId,
		CardId:         []int32{roleStarConfig.Skill1CardId, roleStarConfig.Skill2CardId},
		Attr:           pbProp,
		Passive:        passiveSkill,
		Attack:         normalAttackQueue,
		CfgEffect:      pbModifySkillEffectList,
		CfgEffectParam: pbModifySkillEffectParamList,
		RoleTag:        roleConfig.TagList,
	}
}

func PacketPbIntArrayArray(a [][]int32) []*pb.ParamList {
	r := make([]*pb.ParamList, 0, len(a))
	for _, v := range a {
		rr := make([]int32, 0, len(v))
		for _, vv := range v {
			rr = append(rr, vv)
		}
		r = append(r, &pb.ParamList{
			Value: rr,
		})
	}
	return r
}
